package hyl.core.net;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;

import hyl.core.run.MyRun;

/*服务器端，:接收客户端发送过来的数据并显示，
 *服务器把上接收到的数据加上"echo from service:"再发送回去*/
public class NioClient implements Runnable {

	/* 服务器地址 */

	SocketChannel _client = null;
	Selector selector;

	public NioClient(String ip, int port) throws IOException {
		ini(new InetSocketAddress(ip, port));
	}

	void setReader(NioReader _reader) {
		try {
			_client.register(selector, SelectionKey.OP_READ, _reader);
		} catch (ClosedChannelException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	protected void ini(SocketAddress sa) throws IOException {
		/* 创建TCP通道 */
		_client = SocketChannel.open();
		/* 设置通道为非阻塞 */
		_client.configureBlocking(false);
		/* 向服务器发起连接,一个通道代表一条tcp链接 */
		_client.connect(sa);
		/* 等待三次握手完成 */
		while (!_client.finishConnect()) {
			;
		}
		System.out.println("与服务器的连接建立成功");
		/* 注册感兴趣事件 */

		/* 创建选择器 */
		selector = Selector.open();

	}

	// 不开启接收的情况下 只能发送
	public void run() {

		/* 与服务器断开或线程被中断则结束线程 */
		try {
			while (!Thread.currentThread().isInterrupted()) {
				/* 阻塞等待 */
				selector.select();
				/* Set中的每个key代表一个通道 */
				Set<SelectionKey> keySet = selector.selectedKeys();
				Iterator<SelectionKey> it = keySet.iterator();

				/* 遍历每个已就绪的通道，处理这个通道已就绪的事件 */
				while (it.hasNext()) {
					SelectionKey key = it.next();
					NioReader reader = (NioReader) key.attachment();

					/* 防止下次select方法返回已处理过的通道 */
					/* 表示底层socket的读缓冲区有数据可读 */
					if (key.isReadable()) {
						reader.read(key);
					}
					System.out.println("---");
					it.remove();
				}
			}
		} catch (IOException e) {
			System.out.println(" 连接错误,请检查连接参数!");
		} finally {
			close();
		}
	}

	public boolean send(byte[] 数据包) {
		return MySocket.sendBytes(_client, 数据包);
	}

	public void close() {
		try {
			_client.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	static MyRun _mr;

	public static void startReader(NioClient srv, NioReader 接收器) {
		srv.setReader(接收器);
		if (_mr == null)
			_mr = MyRun.getInstance("客户端", 0);
		_mr.execute(srv);
	}

	public static void exit() {

		_mr.close();

	}

}
